#pragma once
#include "RayTracing.h"

float RayTrace::triangleArea2(Vector plane_data_1,Vector plane_data_2,Vector plane_data_3)
{	
	float a = sqrt((plane_data_1.x-plane_data_2.x)*(plane_data_1.x-plane_data_2.x)+
				   (plane_data_1.y-plane_data_2.y)*(plane_data_1.y-plane_data_2.y)+
				   (plane_data_1.z-plane_data_2.z)*(plane_data_1.z-plane_data_2.z));
	float b = sqrt((plane_data_2.x-plane_data_3.x)*(plane_data_2.x-plane_data_3.x)+
				   (plane_data_2.y-plane_data_3.y)*(plane_data_2.y-plane_data_3.y)+
				   (plane_data_2.z-plane_data_3.z)*(plane_data_2.z-plane_data_3.z));
	float c = sqrt((plane_data_3.x-plane_data_1.x)*(plane_data_3.x-plane_data_1.x)+
				   (plane_data_3.y-plane_data_1.y)*(plane_data_3.y-plane_data_1.y)+
				   (plane_data_3.z-plane_data_1.z)*(plane_data_3.z-plane_data_1.z));
	float s = (a+b+c)/2;
	return (sqrt(s*(s-a)*(s-b)*(s-c)));
}

bool RayTrace::check_plane(Plane p)
{	
	if(abs(triangleArea2(p.plane_v1,p.plane_v2,p.plane_v3)-triangleArea2(p.plane_v1,p.plane_v2,p.intersection)-triangleArea2(p.plane_v2,p.plane_v3,p.intersection)
					-triangleArea2(p.plane_v3,p.plane_v1,p.intersection))<0.5 || abs(triangleArea2(p.plane_v3,p.plane_v4,p.plane_v1)-triangleArea2(p.plane_v3,p.plane_v4,p.intersection)-
					triangleArea2(p.plane_v4,p.plane_v1,p.intersection)-triangleArea2(p.plane_v1,p.plane_v3,p.intersection))<0.5 )
					return true;
	else
		return false;
}

Pixel RayTrace::r_trace(Ray ray,vector<Plane*> planes,Light light,Ray indirectLightRay)
{
	Pixel *color = new Pixel[1];
	Color finalcolor;
	color->a=255;

	for(int i=0;i<planes.size();i++)
	{
		//We hit a plane and it is within the bounds
		if(planes[i]->findIntersection(ray)&& check_plane(*planes[i])){		
				Vector normalize_intersection = planes[i]->intersection;
				normalize_intersection.normalize();
				if(normalize_intersection*light.Direction<=0) normalize_intersection.invert();

				Ray shadowRay;
				shadowRay.origin = planes[i]->intersection;
				shadowRay.Direction = (planes[i]->intersection - light.position);
				shadowRay.Direction.invert();
				bool shadow = false;
				
				for(int j=0;j<planes.size();j++)
				{
					//We hit a plane and it is within the bounds
					if(planes[j]->findIntersection(shadowRay)&& check_plane(*planes[j]) &&planes[j]->plane_name != planes[i]->plane_name && 
						planes[j]->plane_name.compare("table")==0){
						shadow = true;
						break;
					}
				}
				if(shadow)
				{
					color->r=0;
					color->g=0;
					color->b=0;
					return (*color);
				}
				finalcolor = planes[i]->color * (normalize_intersection*light.Direction);

				if(1){//planes[i]->plane_name.compare("ground")==0 || planes[i]->plane_name.compare("table")==0){					
					color->r=finalcolor.red;
					color->g=finalcolor.green;
					color->b=finalcolor.blue;				
					return (*color);			
				}else{					
					indirectLightRay.Direction = planes[i]->intersection - indirectLightRay.origin;
					Vector table_normalized = indirectLightRay.origin;
					table_normalized.normalize();
					float brightness = 0.5;
					float len = (planes[i]->intersection- indirectLightRay.origin).length();
					float radiant_intensity = brightness * (normalize_intersection*indirectLightRay.Direction);
					float calc = planes[i]->normal*(planes[i]->intersection- indirectLightRay.origin);
					float calc_2 = normalize_intersection*(indirectLightRay.origin - planes[i]->intersection);
					float irradiance = max(0,calc)*max(0,calc_2)/pow(len,4);
					//finalcolor = finalcolor*(radiant_intensity*irradiance);
					color->r=finalcolor.red;
					color->g=finalcolor.green;
					color->b=finalcolor.blue;				
					return (*color);	
				}				
		}
	}
	//No intersection set Background to Black			
	color->r=0;
	color->g=0;
	color->b=0;
	return (*color);
}
